package org.kl.bf.web.base;

import java.beans.PropertyEditorSupport;
import java.io.IOException;
import java.io.Serializable;
import java.sql.Date;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import me.chanjar.weixin.mp.api.WxMpService;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.joda.time.DateTime;
import org.kl.bf.entity.BusinessEntity;
import org.kl.bf.entity.basic.CodeValues;
import org.kl.bf.entity.basic.Role;
import org.kl.bf.entity.basic.User;
import org.kl.bf.entity.easyui.EasyuiTreeNode;
import org.kl.bf.entity.easyui.Json;
import org.kl.bf.service.ServiceException;
import org.kl.bf.service.basic.CodeValuesService;
import org.kl.bf.service.basic.OrganizationService;
import org.kl.bf.service.basic.PostService;
import org.kl.bf.service.basic.RoleService;
import org.kl.bf.service.basic.ShiroDbRealm.ShiroUser;
import org.kl.bf.service.basic.UserService;
import org.kl.bf.utils.ApplicationContextHelper;
import org.kl.bf.utils.BasicConstants;
import org.kl.bf.utils.ExcelWriter;
import org.kl.auditsupervision.service.fnd.EmployeeService;
import org.kl.wx.entity.App;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springside.modules.mapper.JsonMapper;


/**
 * @Author hqm
 * @CreateTime 2014-3-14 下午7:37:16
 */
public class BasicController {
	protected static final String PAGE_SIZE = "15";
	protected static final String SEARCH_PREFIX = "search_";// 页面搜索条件前缀
	protected static final String FOOTER_PREFIX = "footer_";// 求和条件前缀
	public static JsonMapper jsonMapper = JsonMapper.nonEmptyMapper();// Json转换器
	public static final Logger logger = LoggerFactory.getLogger("ConsoleInfoFile");

	@Autowired
	protected CodeValuesService codeValuesService;

	@Autowired
	protected OrganizationService organizationService;

	@Autowired
	protected PostService postService;

	@Autowired
	protected UserService userService;
	
	@Autowired
	protected EmployeeService employeeService;
	
	@Autowired
	protected RoleService roleService;
	/**
	 * Excel导出的工具方法（文件名后面不跟时间）
	 * 
	 * @param resultClazz
	 * @param response
	 * @param result
	 * @param fileName
	 */
	protected <T extends Serializable> void exportFilenameNoTime(Class<T> resultClazz, HttpServletResponse response, List<T> result,
			String fileName) {
		try {
			// 输出Excel文件.
			response.setContentType("application/vnd.ms-excel");
			response.setHeader(
					"Content-Disposition",
					"attachment;filename=\""
							+ new String((fileName + ".xls")
									.getBytes("gb2312"), "ISO8859-1") + "\"");
			ExcelWriter.exportExcel(fileName, resultClazz, result, response.getOutputStream());
		} catch (IOException e) {
			e.printStackTrace();
			logger.error("Excel导出失败：" + e.getMessage());
		} finally {
			try {
				response.getOutputStream().flush();
				response.getOutputStream().close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * Excel导出的工具方法
	 * 
	 * @param resultClazz
	 * @param response
	 * @param result
	 * @param fileName
	 */
	protected <T extends Serializable> void export(Class<T> resultClazz, HttpServletResponse response, List<T> result,
			String fileName) {
		try {
			// 输出Excel文件.
			response.setContentType("application/vnd.ms-excel");
			response.setHeader(
					"Content-Disposition",
					"attachment;filename=\""
							+ new String((fileName + new DateTime().toString("yyyyMMddHHmmss") + ".xls")
									.getBytes("gb2312"), "ISO8859-1") + "\"");
			ExcelWriter.exportExcel(fileName, resultClazz, result, response.getOutputStream());
		} catch (IOException e) {
			e.printStackTrace();
			logger.error("Excel导出失败：" + e.getMessage());
		} finally {
			try {
				response.getOutputStream().flush();
				response.getOutputStream().close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * Excel导出的工具方法,选择性导出列
	 * 
	 * @param resultClazz
	 * @param response
	 * @param result
	 * @param fileName
	 */
	protected <T extends Serializable> void exportInclude(Class<T> resultClazz, HttpServletResponse response, List<T> result,List<String> includeField,
			String fileName) {
		try {
			// 输出Excel文件.
			response.setContentType("application/vnd.ms-excel");
			response.setHeader(
					"Content-Disposition",
					"attachment;filename=\""
							+ new String((fileName + new DateTime().toString("yyyyMMddHHmmss") + ".xls")
									.getBytes("gb2312"), "ISO8859-1") + "\"");
			ExcelWriter.exportExcelInclude(fileName, resultClazz, result,includeField, response.getOutputStream());
		} catch (IOException e) {
			e.printStackTrace();
			logger.error("Excel导出失败：" + e.getMessage());
		} finally {
			try {
				response.getOutputStream().flush();
				response.getOutputStream().close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * Excel导出的工具方法_多个实体
	 * 
	 * @param resultClazz
	 * @param response
	 * @param result
	 * @param fileName
	 */
	protected <T,T2,T3,T4,T5 extends Serializable> void exportMoreSheet(Class<T> resultClazz, HttpServletResponse response, List<T> result,
			String fileName,Class<T2> resultClazz2,List<T2> result2,String fileName2,Class<T3> resultClazz3,List<T3> result3,String fileName3,Class<T4> resultClazz4,List<T4> result4,String fileName4,Class<T5> resultClazz5,List<T5> result5,String fileName5) {
		try {
			// 输出Excel文件.
			response.setContentType("application/vnd.ms-excel");
			response.setHeader(
					"Content-Disposition",
					"attachment;filename=\""
							+ new String((fileName + new DateTime().toString("yyyyMMddHHmmss") + ".xls")
									.getBytes("gb2312"), "ISO8859-1") + "\"");
			ExcelWriter.exportExcelMoreSheet(fileName, resultClazz, result,resultClazz2, result2,fileName2,resultClazz3, result3,fileName3,resultClazz4, result4,fileName4,resultClazz5, result5,fileName5, response.getOutputStream());
		} catch (IOException e) {
			e.printStackTrace();
			logger.error("Excel导出失败：" + e.getMessage());
		} finally {
			try {
				response.getOutputStream().flush();
				response.getOutputStream().close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 检查业务单据状态
	 * @param clazz
	 */
	protected <T extends Serializable> void entityStatusValidate(T clazz) {
		if (clazz instanceof BusinessEntity) {
			BusinessEntity one = (BusinessEntity) clazz;
			if(StringUtils.isNotBlank(one.getId()) && !one.getConfirmFlag().equals(BasicConstants.CONFIRM_STATUS_Draft)){
				throw new ServiceException("非草稿状态单据不能更改");
			}
		}
	}
	
	/**
	 * 取出Shiro中的当前用户Id.
	 */
	public static String getCurrentUserId() {
		ShiroUser su = getShiroUser();
		return su == null ? "" : su.id;
	}

	/**
	 * 取出Shiro中的当前用户loginName.
	 */
	public static String getCurrentUserLoginName() {
		ShiroUser su = getShiroUser();
		return su == null ? "" : su.loginName;
	}

	/**
	 * 取出Shiro中的当前用户loginName.
	 */
	public static List<String> getCurrentUserRoleNoList() {
		ShiroUser su = getShiroUser();
		return su == null ? null : su.roleNoList;
	}

	/**
	 * 取出Shiro中的当前用户姓名.
	 */
	public static String getCurrentUserName() {
		ShiroUser su = getShiroUser();
		return su == null ? "" : su.name;
	}
	
	/**
	 * 判断当前用户是否有某个权限
	 * @param permissions
	 * @return
	 */
	public static boolean isPermission(String permissions){
		boolean result = false;
		Subject currentUser = SecurityUtils.getSubject();
		if(currentUser!=null){
			result = currentUser.isPermitted(permissions);
		}
		return result;
	}
	
	/**
	 * 按角色功能配置授权,全局查询--只看自己创建的
	 */
	protected static void queryFilter(Map<String, Object> searchParams,String controller) {
		if(!isPermission(controller+":allQuery")){
			//if(isPermission(controller+":personQuery")){
				createUserFilter(searchParams);
			//}
		}
	}
	
	/**
	 * 按角色功能配置授权,全局查询--只看自己创建的
	 */
	protected static void queryFilter2(Map<String, Object> searchParams,String controller) {
		if(!isPermission(controller+":allQuery")){
			if(isPermission(controller+":personQuery")){
				searchParams.put("EQ_headTeacherId", getCurrentUserId());
			}
		}
	}
	
	/**
	 * 判断当前用户是否是系统管理员.
	 */
	public static boolean isSysManager() {
		ShiroUser su = getShiroUser();
		return su == null || su.sysManager == null || su.sysManager != 1 ? false : true;
	}
	

	/**
	 * Qken 2014-04-10 取出Shiro中的当前用户部门id
	 */
	public static String getCurrentUserDeptId() {
		ShiroUser su = getShiroUser();
		return su == null ? "" : su.deptId;
	}

	/**
	 * 取出Shiro中的当前用户部门名称
	 * 
	 * @return
	 */
	public static String getCurrentUserDeptName() {
		ShiroUser su = getShiroUser();
		return su == null ? "" : su.deptName;
	}
	
	/**
	 * 取出Shiro中的当前用户部门编码
	 * 
	 * @return
	 */
	public static String getCurrentUserDeptCode() {
		ShiroUser su = getShiroUser();
		return su == null ? "" : su.deptCode;
	}
	
	/**
	 * 取出Shiro中的当前用户所属一级部门编码
	 * @return
	 */
	public static String getCurrentUserRootDeptCode() {
		ShiroUser su = getShiroUser();
		return su == null ? "" : su.rootDeptCode;
	}

	/**
	 * 取出Shiro中的当前用户数据角色
	 * 
	 * @return
	 */
	public static Map<String, String> getCurrentUserDataDetail() {
		ShiroUser su = getShiroUser();
		return su == null ? null : su.dataRoleMap;
	}
	
	/**
	 * 获取当前时间
	 * @return
	 */
	public static Timestamp getCurrentTimes() {
		return new Timestamp(System.currentTimeMillis());
	}

	/**
	 * Qken 2014-04-10 取出Shiro中的当前用户
	 * 
	 * @return
	 */
	private static ShiroUser getShiroUser() {
		SecurityUtils.setSecurityManager((org.apache.shiro.web.mgt.DefaultWebSecurityManager) ApplicationContextHelper
				.getBean("securityManager"));
		Subject subject = SecurityUtils.getSubject();
		if (subject != null) {
			return (ShiroUser) subject.getPrincipal();
		}
		return null;
	}

	/**
	 * Ajax请求回应
	 * 
	 * @param msg
	 * @param success
	 * @param obj
	 * @return
	 */
	protected String ajaxMsg(String msg, boolean success, Object obj) {
		Json json = new Json();
		json.setMsg(msg);
		json.setSuccess(success);
		json.setObj(obj);
		return jsonMapper.toJson(json);
	}

	protected String bindingMsg(BindingResult result) {
		StringBuilder sb = new StringBuilder();
		for (FieldError oe : result.getFieldErrors()) {
			sb.append(oe.getField() + " " + oe.getDefaultMessage()).append("<br/>");
		}
		return sb.toString();
	}

	protected String ajaxMsg(Json json) {
		return jsonMapper.toJson(json);
	}

	/**
	 * Qken 2014-04-10 通用代码表获取
	 * 
	 * @param tableId
	 * @return
	 */
	protected String jsonCodeValuesByTableNo(String tableId) {
		List<CodeValues> codeValues = codeValuesService.findByTableId(tableId, 0);
		List<EasyuiTreeNode> plainTree = new ArrayList<EasyuiTreeNode>();
		for (CodeValues cv : codeValues) {
			EasyuiTreeNode one = new EasyuiTreeNode();
			one.setId(cv.getId());
			one.setText(cv.getCodeName());
			one.setPid(cv.getPid());
			one.setIconCls(cv.getIconCls());
			plainTree.add(one);
		}
		String result = jsonMapper.toJson(plainTree);
		return result;
	}

	/**
	 * Qken 2014-04-10 添加过滤条件:当前用户只能看到由所在部门创建的数据。
	 * 
	 * @param searchParams
	 */
	protected static void createDeptFilter(Map<String, Object> searchParams) {
		if (!searchParams.containsKey("EQ_createDept"))
			searchParams.put("EQ_createDept", getCurrentUserDeptId());
	}

	/**
	 * @author QJ 添加过滤条件：当前用户只能看到自己创建的数据
	 * @param searchParams
	 */
	protected static void createUserFilter(Map<String, Object> searchParams) {
		if (!searchParams.containsKey("EQ_createBy"))
			searchParams.put("EQ_createBy", getCurrentUserId());
	}
	

	/**
	 * 
	 * @param codeValue
	 * @return
	 */
	protected String getCodeNameByCodeValue(String codeValue) {
		return codeValuesService.getCodeNameByCodeValue(codeValue);
	}
	
	/**
	 * 
	 * @param tableCode
	 * @return
	 */
	
	protected List<CodeValues> getCodeValuesByTableCode(String tableCode) {
		return codeValuesService.findByTableCode(tableCode);
	}

	@InitBinder
	public void InitBinder(WebDataBinder dataBinder) {
		dataBinder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
			public void setAsText(String value) {
				try {
					if (value.length() == 19)
						setValue(new Date(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value).getTime()));
					else if (value.length() == 16)
						setValue(new Date(new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(value).getTime()));
					else if (value.length() == 13)
						setValue(new Date(new SimpleDateFormat("yyyy-MM-dd HH").parse(value).getTime()));
					else if (value.length() == 10)
						setValue(new Date(new SimpleDateFormat("yyyy-MM-dd").parse(value).getTime()));
					else if (value.length() == 7)
						setValue(new Date(new SimpleDateFormat("yyyy-MM").parse(value).getTime()));
				} catch (ParseException e) {
					setValue(null);
				}
			}

			public String getAsText() {
				return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) getValue());
			}

		});
		dataBinder.registerCustomEditor(Timestamp.class, new PropertyEditorSupport() {
			public void setAsText(String value) {
				try {
					if (value.length() == 19)
						setValue(new Timestamp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value).getTime()));
					else if (value.length() == 16)
						setValue(new Timestamp(new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(value).getTime()));
					else if (value.length() == 13)
						setValue(new Timestamp(new SimpleDateFormat("yyyy-MM-dd HH").parse(value).getTime()));
					else if (value.length() == 10)
						setValue(new Timestamp(new SimpleDateFormat("yyyy-MM-dd").parse(value).getTime()));
					else if (value.length() == 7)
						setValue(new Timestamp(new SimpleDateFormat("yyyy-MM").parse(value).getTime()));
				} catch (ParseException e) {
					setValue(null);
				}
			}

			public String getAsText() {
				return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Timestamp) getValue());
			}

		});
	}

	/**
	 * 获取系统配置
	 */
	public String getConfig(HttpSession session, String configNo) {
		if (session != null) {
			return (String) session.getServletContext().getAttribute(configNo);
		} else {
			return null;
		}
	}

	/**
	 * 通过Token获取微信配置WxMpService
	 * 
	 * @param session
	 * @param token
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public WxMpService getWxMpServiceByToken(HttpSession session, String token) {
		if (session != null) {
			Map<String, WxMpService> token_wxMpServiceMap = (Map<String, WxMpService>) session.getServletContext()
					.getAttribute(BasicConstants.SC_WXMPSERVICE_TOKEN_MAP);
			if (token_wxMpServiceMap != null && token_wxMpServiceMap.containsKey(token)) {
				return token_wxMpServiceMap.get(token);
			}
		}
		return null;
	}

	/**
	 * 通过AppId获取微信配置WxMpService
	 * 
	 * @param session
	 * @param appId
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public WxMpService getWxMpServiceByAppId(HttpSession session, String appId) {
		if (session != null) {
			Map<String, WxMpService> appId_wxMpServiceMap = (Map<String, WxMpService>) session.getServletContext()
					.getAttribute(BasicConstants.SC_WXMPSERVICE_APPID_MAP);
			if (appId_wxMpServiceMap != null && appId_wxMpServiceMap.containsKey(appId)) {
				return appId_wxMpServiceMap.get(appId);
			}
		}
		return null;
	}

	/**
	 * 通过AppId获取微信配置：APP
	 * 
	 * @param session
	 * @param appId
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public App getWxAppByAppId(HttpSession session, String appId) {
		if (session != null) {
			Map<String, App> appId_AppMap = (Map<String, App>) session.getServletContext().getAttribute(
					BasicConstants.SC_WXAPP_APPID_MAP);
			if (appId_AppMap != null && appId_AppMap.containsKey(appId)) {
				return appId_AppMap.get(appId);
			}
		}
		return null;
	}

	/**
	 * 通过Token获取微信配置：APP
	 * 
	 * @param session
	 * @param token
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public App getWxAppByToken(HttpSession session, String token) {
		if (session != null) {
			Map<String, App> token_AppMap = (Map<String, App>) session.getServletContext().getAttribute(
					BasicConstants.SC_WXAPP_TOKEN_MAP);
			if (token_AppMap != null && token_AppMap.containsKey(token)) {
				return token_AppMap.get(token);
			}
		}
		return null;
	}

	public static void dataPermissionsFilter(Map<String, Object> searchParams) {
		if (!BasicController.isSysManager()) {
			Map<String, String> dataDetailMap = BasicController.getCurrentUserDataDetail();
			// if (dataDetailMap.containsKey(BasicConstants.Company_Type)) {
			searchParams.put("IN_companyType.companyType", dataDetailMap.get(BasicConstants.Company_Type));
			// }
		}
	}

	public static void dataPermissionsFilter(Map<String, Object> searchParams, HttpSession session) {
		dataPermissionsFilter(searchParams);
		searchParams.put("EQ_companyType.id", session.getAttribute(BasicConstants.DEFAULTCOMPANYTYPEID));
	}

	/**
	 * 增加公司类型数据权限过滤，公司类型搜索字段自定义，即不是本表的公司类型
	 * 
	 * @param searchParams
	 * @param searchCompanyTypeProperty
	 */
	public static void dataPermissionsFilter(Map<String, Object> searchParams, String searchCompanyTypeProperty) {
		if (!StringUtils.isBlank(searchCompanyTypeProperty)) {
			if (!BasicController.isSysManager()) {
				Map<String, String> dataDetailMap = BasicController.getCurrentUserDataDetail();
				searchParams.put("IN_" + searchCompanyTypeProperty + ".companyType",
						dataDetailMap.get(BasicConstants.Company_Type));
			}
		} else {
			if (!BasicController.isSysManager()) {
				Map<String, String> dataDetailMap = BasicController.getCurrentUserDataDetail();
				searchParams.put("IN_companyType", dataDetailMap.get(BasicConstants.Company_Type));
			}
		}
	}

	/**
	 * 增加公司类型数据权限过滤，公司类型搜索字段自定义，即不是本表的公司类型 只显示当前Session CompanyType的数据
	 * 
	 * @param searchParams
	 * @param session
	 * @param searchCompanyTypeProperty
	 */
	public static void dataPermissionsFilter(Map<String, Object> searchParams, HttpSession session,
			String searchCompanyTypeProperty) {
		if (!StringUtils.isBlank(searchCompanyTypeProperty)) {
			if (!BasicController.isSysManager()) {
				Map<String, String> dataDetailMap = BasicController.getCurrentUserDataDetail();
				searchParams.put("IN_" + searchCompanyTypeProperty + ".companyType",
						dataDetailMap.get(BasicConstants.Company_Type));
			}
			searchParams.put("EQ_" + searchCompanyTypeProperty + ".id",
					session.getAttribute(BasicConstants.DEFAULTCOMPANYTYPEID));
		} else {
			if (!BasicController.isSysManager()) {
				Map<String, String> dataDetailMap = BasicController.getCurrentUserDataDetail();
				searchParams.put("IN_companyType", dataDetailMap.get(BasicConstants.Company_Type));
			}
			searchParams.put("EQ_id", session.getAttribute(BasicConstants.DEFAULTCOMPANYTYPEID));
		}
	}
	
	/**
	 * 判定当前用户是否是班主任
	 * @return
	 */
	public boolean isHeadTeacher(){
		Role role=roleService.findByRoleNo("headTeacher");
		if(isSpecifiedRole(role.getId())){
			return true;
		}else{
			return false;
		}
	}
	
	/**
	 * 判定当前用户是否为教务员
	 * @return
	 */
	public boolean isJiaoWuYuan(){
		Role role=roleService.findByRoleNo("teacherHour");
		if(isSpecifiedRole(role.getId())){
			return true;
		}else{
			return false;
		}
	}
	
	/**
	 * 判定当前用户是否是任课老师
	 * @return
	 */
	public boolean isTeachNormalTeacher(){
		Role role=roleService.findByRoleNo("teachNormalTeacher");
		if(isSpecifiedRole(role.getId())){
			return true;
		}else{
			return false;
		}
	}
	
	/**
	 * 判定当前用户是否有指定的角色
	 * @param roleId
	 * @return
	 */
	public boolean isSpecifiedRole(String roleId){
		User user=userService.getUser(getCurrentUserId());
		Set<Role>  roleList=user.getRoleSet();
		for(Role a:roleList){
			if(a.getId().equals(roleId)){
				return true;
			}
		}
		return false;
	}
}
